﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;
using YJKOpeningCommon.DataEnum;
using YJKOpeningCommon.OpeningEX;
using YJKExcelFormTool;
using YJKExcelFormTool.Designer;

namespace YJKOpeningCommon.OpeningDim
{
	public class OpeningDim
	{
		public OpeningDim(Autodesk.Revit.DB.Document doc)
		{
			this.m_doc = doc;
			if (this.m_lstOpeningDim == null)
			{
				this.m_lstOpeningDim = new Dictionary<IndependentTag, Element>();
				this.GetAllOpeningDim();
			}
		}

		private void GetAllOpeningDim()
		{
			foreach (Element element in YJKElementFilter.GetElementByClass(typeof(IndependentTag), this.m_doc))
			{
				IndependentTag independentTag = element as IndependentTag;
				if (independentTag != null && independentTag.TaggedLocalElementId != null)
				{
					this.m_lstOpeningDim.Add(independentTag, null);
				}
			}
		}

		private void DelOpeningDim(ElementId openingId)
		{
			foreach (KeyValuePair<IndependentTag, Element> keyValuePair in this.m_lstOpeningDim)
			{
				IndependentTag key = keyValuePair.Key;
				Element value = keyValuePair.Value;
				if (key.TaggedLocalElementId == openingId)
				{
					this.m_doc.Delete(key.Id);
					this.m_lstOpeningDim.Remove(key);
					break;
				}
			}
		}

		private void DelOpeningDimByStrNum(string strTagNum)
		{
			foreach (KeyValuePair<IndependentTag, Element> keyValuePair in this.m_lstOpeningDim)
			{
				IndependentTag key = keyValuePair.Key;
				Element value = keyValuePair.Value;
				if (key.TagText == strTagNum)
				{
					this.m_doc.Delete(key.Id);
					if (value != null)
					{
						value.GetParameter("标记").Set("");
					}
					this.m_lstOpeningDim.Remove(key);
					break;
				}
			}
		}

		public IndependentTag CreateDim(XYZ ptPos, XYZ ptDim, bool isContainCircle, Element elem)
		{
			bool isEquipOpening = this.isEquipOpeing(elem);
			string labelDimFamilyName = this.GetLabelDimFamilyName(ptPos, ptDim, isContainCircle, isEquipOpening);
			FamilySymbol familySymbol = this.LoadOpeningDimFamily(labelDimFamilyName);
			if (familySymbol == null)
			{
				return null;
			}
			IndependentTag independentTag = this.CreateOpeningLabelDim(familySymbol, elem, ptPos, ptDim);
			if (independentTag != null)
			{
				return independentTag;
			}
			return null;
		}

		private bool isEquipOpeing(Element elem)
		{
			string paramName = "尺寸";
			Parameter parameter = elem.GetParameter(paramName);
			if (parameter == null)
			{
				return true;
			}
			string input = parameter.AsString();
			string pattern = "暗装消火栓|暗装配电箱|分集水器";
			return Regex.IsMatch(input, pattern);
		}

		public void SetOpeningDim(EDimItemType dimType, Element elem)
		{
			if (dimType == EDimItemType.eUnknown)
			{
				return;
			}
			string paramName = StrEdimItemType.m_strEdimItemType[(int)dimType];
			Parameter parameter = elem.GetParameter(paramName);
			if (parameter == null)
			{
				return;
			}
			string text = parameter.AsString();
			parameter = elem.GetParameter("标注标高");
			if (parameter == null)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_doc, "SetOpeningDimLevel");
			try
			{
				transaction.Start();
				parameter.Set(text);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		public void DeleteOpeningDim(ref string dimUniqueId)
		{
			if (dimUniqueId == null || dimUniqueId == "")
			{
				return;
			}
			Element element = this.m_doc.GetElement(dimUniqueId);
			if (element == null)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_doc, "DeleteDim");
			try
			{
				transaction.Start();
				this.m_doc.DeleteElement(element);
				transaction.Commit();
				dimUniqueId = "";
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private string GetLabelDimFamilyName(XYZ ptPos, XYZ ptDim, bool isContainCircle, bool isEquipOpening)
		{
			string result;
			if (ptDim.X > ptPos.X)
			{
				if (isContainCircle)
				{
					if (isEquipOpening)
					{
						result = "洞口标注-右-带圆圈-设备";
					}
					else
					{
						result = "洞口标注-右-带圆圈";
					}
				}
				else if (isEquipOpening)
				{
					result = "洞口标注-右-不带圆圈-设备";
				}
				else
				{
					result = "洞口标注-右-不带圆圈";
				}
			}
			else if (isContainCircle)
			{
				if (isEquipOpening)
				{
					result = "洞口标注-左-带圆圈-设备";
				}
				else
				{
					result = "洞口标注-左-带圆圈";
				}
			}
			else if (isEquipOpening)
			{
				result = "洞口标注-左-不带圆圈-设备";
			}
			else
			{
				result = "洞口标注-左-不带圆圈";
			}
			return result;
		}

		private FamilySymbol LoadOpeningDimFamily(string familyName)
		{
			FamilySymbol familySymbol = YJKRevitTools.GetFamilySymbol(familyName, this.m_doc);
			if (familySymbol != null)
			{
				return familySymbol;
			}
			Transaction transaction = new Transaction(this.m_doc);
			transaction.Start("LoadFamily");
			try
			{
				string text = Path.Combine(Product.FamilyLocation, RevitVersion.Version, "OpeningDim", familyName + ".rfa");
				this.m_doc.LoadFamily(text);
				familySymbol = YJKRevitTools.GetFamilySymbol(familyName, this.m_doc);
				transaction.Commit();
				return familySymbol;
			}
			catch
			{
				transaction.RollBack();
			}
			YJKMessageBox.Show("加载族 " + familyName + " 失败！");
			return null;
		}

		private IndependentTag CreateOpeningLabelDim(FamilySymbol dimSymbol, Element opening, XYZ ptPos, XYZ ptDim)
		{
			Transaction transaction = new Transaction(this.m_doc);
			IndependentTag result;
			try
			{
				transaction.Start("CreateDimTag");
				UnifiedModified.ActivateFamilySymbol(dimSymbol);
				IndependentTag independentTag = RevitVersionFuncs.NewTag(this.m_doc, this.m_doc.ActiveView, new Reference(opening), false, 0, 0, ptDim);
				if (independentTag != null)
				{
					independentTag.ChangeTypeId(new ElementId(dimSymbol.Id.IntegerValue));
					independentTag.HasLeader = true;
                    independentTag.LeaderEndCondition = (LeaderEndCondition)1;
					independentTag.LeaderEnd = ptPos;
				}
				transaction.Commit();
				result = independentTag;
			}
			catch (Exception)
			{
				transaction.RollBack();
				result = null;
			}
			return result;
		}

		private List<CellInfo> GetOpeningDimCellInfo(List<Element> lstOpening, string strDimPrefixItem, EDimItemType circleOpeningDimType, EDimItemType rectOpeningDimType, ref int rowCount, ref int colCount)
		{
			rowCount = lstOpening.Count + 1;
			colCount = 4;
			List<CellInfo> list = new List<CellInfo>();
			list.Add(new CellInfo(0, 0, 0, 0, "编号", CellInfo.CellInfoType.CIT_Text));
			list.Add(new CellInfo(0, 0, 1, 1, "尺寸", CellInfo.CellInfoType.CIT_Text));
			list.Add(new CellInfo(0, 0, 2, 2, "标高", CellInfo.CellInfoType.CIT_Text));
			list.Add(new CellInfo(0, 0, 3, 3, "专业", CellInfo.CellInfoType.CIT_Text));
			string text = string.Empty;
			string text2 = string.Empty;
			string text3 = string.Empty;
			string text4 = string.Empty;
			OpeningXData openingXData = new OpeningXData();
			string paramName = string.Empty;
			for (int i = 1; i <= lstOpening.Count; i++)
			{
				Element element = lstOpening[i - 1];
				if (element != null)
				{
					text4 = string.Empty;
					paramName = string.Empty;
					text = string.Format("{0}{1}", strDimPrefixItem, i);
					openingXData.ReadOpeningXData(element);
					text2 = openingXData.m_strOpeningSize;
					text4 = openingXData.m_strSpeciality;
					EDimItemType edimItemType;
					if (openingXData.m_eOpeningProfile == 0)
					{
						edimItemType = circleOpeningDimType;
					}
					else
					{
						edimItemType = rectOpeningDimType;
					}
					if (edimItemType != EDimItemType.eUnknown)
					{
						int num = (int)edimItemType;
						paramName = StrEdimItemType.m_strEdimItemType[num];
						Parameter parameter = element.GetParameter(paramName);
						if (parameter != null)
						{
							text3 = parameter.AsString();
							if (text3 == null)
							{
								text3 = "";
							}
							list.Add(new CellInfo(i, i, 0, 0, text, CellInfo.CellInfoType.CIT_Text));
							list.Add(new CellInfo(i, i, 1, 1, text2, CellInfo.CellInfoType.CIT_Text));
							list.Add(new CellInfo(i, i, 2, 2, text3, CellInfo.CellInfoType.CIT_Text));
							list.Add(new CellInfo(i, i, 3, 3, text4, CellInfo.CellInfoType.CIT_Text));
						}
					}
				}
			}
			return list;
		}

		public bool DimOpeningTable(ExternalCommandData cmdData, List<Element> lstOpening, string strDimPrefixItem, EDimItemType circleOpeningDimType, EDimItemType rectOpeningDimType)
		{
			int rowCount = 0;
			int colCount = 0;
			List<CellInfo> openingDimCellInfo = this.GetOpeningDimCellInfo(lstOpening, strDimPrefixItem, circleOpeningDimType, rectOpeningDimType, ref rowCount, ref colCount);
			if (openingDimCellInfo.Count < 5)
			{
				YJKMessageBox.Show("提取不到洞标注信息。");
				return false;
			}
			Autodesk.Revit.DB.View activeView = this.m_doc.ActiveView;
			TextNoteType textStyle = YJKElementFilter.GetElementByClass(typeof(TextNoteType), this.m_doc).Cast<TextNoteType>().FirstOrDefault<TextNoteType>();
			string text = "";
			if (TableInterface.DrawGeneralTable(cmdData, rowCount, colCount, openingDimCellInfo, activeView, textStyle, ref text, null, null, true) != null)
			{
				return false;
			}
			this.SetDimNum(lstOpening, strDimPrefixItem, textStyle);
			return true;
		}

		private void SetDimNum(List<Element> lstOpening, string strDimPrefixItem, TextNoteType textStyle)
		{
			FamilySymbol familySymbol = this.LoadOpeningDimFamily("洞口标注-编号");
			if (familySymbol == null)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_doc, "UpdateOpeningNumber");
			try
			{
				transaction.Start();
				int num = 1;
				foreach (Element elem in lstOpening)
				{
					string text = string.Format("{0}{1}", strDimPrefixItem, num);
					this.DelOpeningDimByStrNum(text);
					elem.GetParameter("标记").Set(text);
					num++;
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				YJKMessageBox.Show("更新洞口标记失败");
				if (transaction.HasStarted())
				{
					transaction.RollBack();
					return;
				}
			}
			double dTextH = textStyle.GetParameter(BuiltInParameter.TEXT_SIZE).AsDouble() * (double)this.m_doc.ActiveView.Scale;
			Transaction transaction2 = new Transaction(this.m_doc);
			transaction2.Start("CreateDimTag");
			foreach (Element element in lstOpening)
			{
				this.DelOpeningDim(element.Id);
				this.CreateOpeningNumberDim(familySymbol, element, dTextH);
			}
			transaction2.Commit();
		}

		private void CreateOpeningNumberDim(FamilySymbol dimSymbol, Element opening, double dTextH)
		{
			if ((opening as FamilyInstance).Host == null)
			{
				return;
			}
			XYZ point = (opening.Location as LocationPoint).Point;
			TagOrientation tagOrientation = 0;
			this.GetOpeningNumberDimParam(opening, dTextH, ref tagOrientation, ref point);
			UnifiedModified.ActivateFamilySymbol(dimSymbol);
			IndependentTag independentTag = RevitVersionFuncs.NewTag(this.m_doc, this.m_doc.ActiveView, new Reference(opening), false, 0, tagOrientation, point);
			if (independentTag != null)
			{
				independentTag.ChangeTypeId(new ElementId(dimSymbol.Id.IntegerValue));
				this.m_lstOpeningDim.Add(independentTag, opening);
			}
		}

		private void GetOpeningNumberDimParam(Element opening, double dTextH, ref TagOrientation orientation, ref XYZ ptDim)
		{
			Element host = (opening as FamilyInstance).Host;
			XYZ point = (opening.Location as LocationPoint).Point;
			if (host is Wall)
			{
				Wall wall = host as Wall;
				Curve curve = (wall.Location as LocationCurve).Curve;
				double num = dTextH + 0.5 * wall.WallType.Width;
				if (curve.GetType() == typeof(Line))
				{
					XYZ hyendPoint = curve.GetEndPoint(0);
					XYZ hyendPoint2 = curve.GetEndPoint(1);
					if (Math.Abs(hyendPoint.X - hyendPoint2.X) > Math.Abs(hyendPoint.Y - hyendPoint2.Y))
					{
						orientation = 0;
						ptDim = point + XYZ.BasisY * num;
						return;
					}
                    orientation = (TagOrientation)1;
					ptDim = point - XYZ.BasisX * num;
					return;
				}
			}
			else
			{
				BoundingBoxXYZ boundingBoxXYZ = (opening as FamilyInstance).get_BoundingBox(this.m_doc.ActiveView);
				double num2 = dTextH + 0.5 * (boundingBoxXYZ.Max.Y - boundingBoxXYZ.Min.Y);
				orientation = 0;
				ptDim = point + XYZ.BasisY * num2;
			}
		}

		private Dictionary<IndependentTag, Element> m_lstOpeningDim;

		private Document m_doc;
	}
}
